{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 金融 证券 图谱搭建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-01-28T05:48:19.517559Z",
     "start_time": "2020-01-28T05:48:19.514553Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "from py2neo import Graph\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def check_result(result):\n",
    "    for c in result :\n",
    "        print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "graph = Graph(\n",
    "    \"http://localhost:7474\",\n",
    "    usernmae=\"neo4j\",\n",
    "    password=\"Neo4j\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于，图谱的更新我们采取 neo4j APOC 中提供的功能——`apoc.periodic.iterate` 过程，批量更新图谱。\n",
    "\n",
    "具体用法可参考下面的网址。\n",
    "\n",
    "网址：https://neo4j.com/docs/labs/apoc/4.2/graph-updates/periodic-execution/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在这里，我们尽可能覆盖实际业务中更新场景\n",
    "\n",
    "- 节点\n",
    "    - 节点标签 labels （新增/删除）\n",
    "    - 节点属性 properities（新增/修改）\n",
    "\n",
    "- 关系\n",
    "    - 关系 （新增）\n",
    "    - 关系属性 properities（新增/修改)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "针对下面两条记录会在更新前后做对比\n",
    "\n",
    "|fund|fullname|ann_date|end_date|mkv|amount|stk_mkv_ratio|stk_float_ratio|type|\n",
    "|--|--|--|--|--|--|--|--|--|\n",
    "|000001|南极电商股份有限公司|20200121|20191231|149832015.87|NotChange|4.31|NotChange|IN_PORTFOLIO|\n",
    "|000001|保利联合化工控股集团股份有限公司|20130328|20121231|8927779.35|363657.0|0.15|0.21|IN_PORTFOLIO|"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新前"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"\"\"\n",
    "MATCH p = (a:FUND)-[r:IN_PORTFOLIO]->(b:COMPANY) \n",
    "WHERE a.fund_code='000001'and  b.company='{}' \n",
    "RETURN a.fund_code as fund_code,a.name as name,b.company as company,r.amount,\n",
    "       r.ann_date,r.end_date,r.mkv,r.stk_float_ratio,r.stk_mkv_ratio\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>company</th>\n",
       "      <th>fund_code</th>\n",
       "      <th>name</th>\n",
       "      <th>r.amount</th>\n",
       "      <th>r.ann_date</th>\n",
       "      <th>r.end_date</th>\n",
       "      <th>r.mkv</th>\n",
       "      <th>r.stk_float_ratio</th>\n",
       "      <th>r.stk_mkv_ratio</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>南极电商股份有限公司</td>\n",
       "      <td>000001</td>\n",
       "      <td>华夏成长</td>\n",
       "      <td>13733457.0</td>\n",
       "      <td>20191022.0</td>\n",
       "      <td>20190930.0</td>\n",
       "      <td>141591936.0</td>\n",
       "      <td>0.72</td>\n",
       "      <td>4.48</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      company fund_code  name    r.amount  r.ann_date  r.end_date  \\\n",
       "0  南极电商股份有限公司    000001  华夏成长  13733457.0  20191022.0  20190930.0   \n",
       "\n",
       "         r.mkv  r.stk_float_ratio  r.stk_mkv_ratio  \n",
       "0  141591936.0               0.72             4.48  "
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph.run(query.format('南极电商股份有限公司')).to_data_frame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "Empty DataFrame\n",
       "Columns: []\n",
       "Index: []"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph.run(query.format('保利联合化工控股集团股份有限公司')).to_data_frame()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 更新图谱"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：公司"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "50 /src/notebooks/data_update/gap/node_companies.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_companies.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_company = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_companies.csv' AS row return row\",\n",
    "    \"with row.fullname as company,\n",
    "          row.name as short_name,\n",
    "          row.symbol as symbol,\n",
    "          row.market as market,\n",
    "          row.exchange as exchange,\n",
    "          row.list_status as list_status,\n",
    "          row.list_date as list_date,\n",
    "          row.delist_date as delist_date,\n",
    "          row.setup_date as setup_date,\n",
    "          row.label as label\n",
    "    MERGE (a:COMPANY {company:company})\n",
    "    SET a.short_name = (CASE WHEN short_name <> 'NotChange' THEN short_name ELSE a.short_name END),\n",
    "        a.symbol = (CASE WHEN symbol <> 'NotChange' THEN symbol ELSE a.symbol END),\n",
    "        a.market = (CASE WHEN market <> 'NotChange' THEN market ELSE a.market END),\n",
    "        a.exchange = (CASE WHEN exchange <> 'NotChange' THEN exchange ELSE a.exchange  END),\n",
    "        a.list_status = (CASE WHEN list_status <> 'NotChange' THEN list_status ELSE a.list_status END),\n",
    "        a.list_date = (CASE WHEN list_date <> 'NotChange' THEN toFloat(list_date) ELSE a.list_date  END),\n",
    "        a.delist_date = (CASE WHEN delist_date <> 'NotChange' THEN toFloat(delist_date) ELSE a.delist_date END),\n",
    "        a.setup_date = (CASE WHEN setup_date <> 'NotChange' THEN setup_date ELSE a.setup_date END)   \n",
    "    FOREACH(t in CASE WHEN 'LISTED_COMPANY' in split(label,';') THEN 1 ELSE null END | SET a:LISTED_COMPANY )\n",
    "    FOREACH(t in CASE WHEN 'FUND_CUSTODIAN' in split(label,';') THEN 1 ELSE null END | SET a:FUND_CUSTODIAN )\n",
    "    FOREACH(t in CASE WHEN 'FUND_MANAGER' in split(label,';') THEN 1 ELSE null END | SET a:FUND_MANAGER )\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_company)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=49 timeTaken=1 committedOperations=49 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 49, 'committed': 49, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：行业"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/node_industries.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_industries.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_industries = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_industries.csv' AS row return row\",\n",
    "    \"with row.industry as industry,\n",
    "          row.label as label\n",
    "    MERGE (a:INDUSTRY {industry:industry})\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_industries)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：城市"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/node_city.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_city.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_city = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_city.csv' AS row return row\",\n",
    "    \"with row.city as city,\n",
    "          row.label as label\n",
    "    MERGE (a:CITY {city:city})\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_city)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：省份"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/node_province.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_province.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_province = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_province.csv' AS row return row\",\n",
    "    \"with row.province as province,\n",
    "          row.label as label\n",
    "    MERGE (a:PROVINCE {province:province})\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_province)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：基金"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "379 /src/notebooks/data_update/gap/node_funds.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_funds.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_funds = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_funds.csv' AS row return row\",\n",
    "    \"with row.fund as fund_code,\n",
    "          row.name as name,\n",
    "          row.fund_type as fund_type,\n",
    "          row.invest_type as invest_type,\n",
    "          row.type as type,\n",
    "          row.benchmark as benchmark,\n",
    "          row.market as market,\n",
    "          row.found_date as found_date,\n",
    "          row.delist_date as delist_date,\n",
    "          row.status as status,\n",
    "          row.label as label\n",
    "    MERGE (a:FUND {fund_code:fund_code})\n",
    "    SET a.name = (CASE WHEN name <> 'NotChange' THEN name ELSE a.name END),\n",
    "        a.fund_type = (CASE WHEN fund_type <> 'NotChange' THEN fund_type ELSE a.fund_type END),\n",
    "        a.invest_type = (CASE WHEN invest_type <> 'NotChange' THEN invest_type ELSE a.invest_type END),\n",
    "        a.type = (CASE WHEN type <> 'NotChange' THEN type ELSE a.type  END),\n",
    "        a.benchmark = (CASE WHEN benchmark <> 'NotChange' THEN benchmark ELSE a.benchmark END),\n",
    "        a.market = (CASE WHEN market <> 'NotChange' THEN market ELSE a.market END),\n",
    "        a.found_date = (CASE WHEN found_date <> 'NotChange' THEN toFloat(found_date) ELSE a.found_date  END),\n",
    "        a.delist_date = (CASE WHEN delist_date <> 'NotChange' THEN toFloat(delist_date) ELSE a.delist_date  END),\n",
    "        a.status = (CASE WHEN status <> 'NotChange' THEN status ELSE a.status END)\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_funds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=378 timeTaken=1 committedOperations=378 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 378, 'committed': 378, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新节点：人"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/node_managers.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/node_managers.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_node_managers = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/node_managers.csv' AS row return row\",\n",
    "    \"with row.hash_cust as manager_id,\n",
    "          row.name as name,\n",
    "          row.gender as gender,\n",
    "          row.edu as edu,\n",
    "          row.national as national,\n",
    "          row.birthday as birthday,\n",
    "          row.label as label\n",
    "    MERGE (a:MANAGER {manager_id:manager_id})\n",
    "    SET a.name = (CASE WHEN name <> 'NotChange' THEN name ELSE a.name END),\n",
    "        a.gender = (CASE WHEN gender <> 'NotChange' THEN gender ELSE a.gender END),\n",
    "        a.edu = (CASE WHEN edu <> 'NotChange' THEN edu ELSE a.edu END),\n",
    "        a.national = (CASE WHEN national <> 'NotChange' THEN national ELSE a.national  END),\n",
    "        a.birthday = (CASE WHEN birthday <> 'NotChange' THEN toFloat(birthday) ELSE a.birthday END)\n",
    "    RETURN a\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_node_managers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：城市-->省份"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/rel_city_in_province.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_city_in_province.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_city_in_province = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_city_in_province.csv' AS row return row\",\n",
    "    \"with row.city as city,\n",
    "          row.province as province,\n",
    "          row.type as type\n",
    "    MERGE (a:CITY {city:city})\n",
    "    MERGE (b:PROVINCE {province:province})\n",
    "    MERGE (a)-[r:IN_PROVINCE]->(b)\n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_city_in_province)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：公司-->城市"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/rel_company_in_city.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_company_in_city.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_company_in_city = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_company_in_city.csv' AS row return row\",\n",
    "    \"with row.fullname as company,\n",
    "          row.city as city,\n",
    "          row.type as type\n",
    "    MERGE (a:COMPANY {company:company})          \n",
    "    MERGE (b:CITY {city:city})\n",
    "    MERGE (a)-[r:IN_CITY]->(b)\n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_company_in_city)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：股票-->行业"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/rel_share_in_industry.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_share_in_industry.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_share_in_industry = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_share_in_industry.csv' AS row return row\",\n",
    "    \"with row.fullname as company,\n",
    "          row.industry as industry,\n",
    "          row.type as type\n",
    "    MERGE (a:COMPANY {company:company})          \n",
    "    MERGE (b:INDUSTRY {industry:industry})\n",
    "    MERGE (a)-[r:IN_INDUSTRY]->(b)\n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:10000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_share_in_industry)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：公司（上市公司）--> 人(董事高管)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于 上市公司 高管情况，其实有另外一种 处理方式，就是参照上面的处理方式把 6 类关系分别拆开用不同的文件进行更新。\n",
    "这里没有做拆分，选择用 `cypher` 判断关系类型更新，速度稍慢。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1252 /src/notebooks/data_update/gap/rel_listed_company_has_manager.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_listed_company_has_manager.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_listed_company_has_manager = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_listed_company_has_manager.csv' AS row return row\",\n",
    "    \"with row.fullname as company,\n",
    "          row.hash_cust as manager_id,\n",
    "          row.begin_date as begin_date,\n",
    "          row.end_date as end_date,\n",
    "          row.title as title,\n",
    "          row.lev as type\n",
    "    MERGE (a:COMPANY {company:company})          \n",
    "    MERGE (b:MANAGER {manager_id:manager_id})\n",
    "    FOREACH(t in CASE WHEN type = '董事会成员' THEN 1 ELSE null END | MERGE (a)-[r:董事会成员 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "                                                                    \n",
    "    FOREACH(t in CASE WHEN type = '高管' THEN 1 ELSE null END | MERGE (a)-[r:高管 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "    FOREACH(t in CASE WHEN type = '委员会成员' THEN 1 ELSE null END | MERGE (a)-[r:委员会成员 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "    FOREACH(t in CASE WHEN type = '监事' THEN 1 ELSE null END | MERGE (a)-[r:监事 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "    FOREACH(t in CASE WHEN type = '核心技术人员' THEN 1 ELSE null END | MERGE (a)-[r:核心技术人员 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "    FOREACH(t in CASE WHEN type = '其他' THEN 1 ELSE null END | MERGE (a)-[r:其他 {title:title,begin_date:toFloat(begin_date)}]->(b) \n",
    "                                                                    SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "                                                                    )\n",
    "    RETURN a,b\n",
    "    \",\n",
    "    {batchSize:1000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在关系匹配时，先对图数据库， 添加索引，提高更新效率\n",
    "result = graph.run(query_rel_listed_company_has_manager)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=2 total=1251 timeTaken=2 committedOperations=1251 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 2, 'committed': 2, 'failed': 0, 'errors': {}} operations={'total': 1251, 'committed': 1251, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：公募基金 --> 托管人"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/rel_fund_has_custodian.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_fund_has_custodian.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_fund_has_custodian = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_fund_has_custodian.csv' AS row return row\",\n",
    "    \"with row.fund as fund_code,\n",
    "          row.fullname as company,\n",
    "          row.type as type\n",
    "    MERGE (a:FUND {fund_code:fund_code})          \n",
    "    MERGE (b:COMPANY {company:company})\n",
    "    MERGE (a)-[r:HAS_CUSTODIAN]->(b)\n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:1000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_fund_has_custodian)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：公募基金 --> 管理人"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 /src/notebooks/data_update/gap/rel_fund_has_management.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_fund_has_management.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_fund_has_management = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_fund_has_management.csv' AS row return row\",\n",
    "    \"with row.fund as fund_code,\n",
    "          row.fullname as company,\n",
    "          row.type as type\n",
    "    MERGE (a:FUND {fund_code:fund_code})          \n",
    "    MERGE (b:COMPANY {company:company})\n",
    "    MERGE (a)-[r:HAS_MANAGEMENT]->(b)\n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:1000, parallel:false})\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_fund_has_custodian)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=1 total=0 timeTaken=0 committedOperations=0 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 1, 'committed': 1, 'failed': 0, 'errors': {}} operations={'total': 0, 'committed': 0, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新关系：公募基金持仓数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "54560 /src/notebooks/data_update/gap/rel_fund_listed_company_portfolio.csv\r\n"
     ]
    }
   ],
   "source": [
    "!wc -l /src/notebooks/data_update/gap/rel_fund_listed_company_portfolio.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_rel_fund_listed_company_portfolio = \"\"\"\n",
    "CALL apoc.periodic.iterate(\n",
    "    \"LOAD CSV WITH HEADERS FROM 'file:///src/notebooks/data_update/gap/rel_fund_listed_company_portfolio.csv' AS row return row\",\n",
    "    \"with row.fund as fund_code,\n",
    "          row.fullname as company,\n",
    "          row.ann_date as ann_date,\n",
    "          row.end_date as end_date,\n",
    "          row.mkv as mkv,\n",
    "          row.amount as amount,\n",
    "          row.stk_mkv_ratio as stk_mkv_ratio,\n",
    "          row.stk_float_ratio as stk_float_ratio,\n",
    "          row.type as type\n",
    "    MERGE (a:FUND {fund_code:fund_code})          \n",
    "    MERGE (b:COMPANY {company:company})\n",
    "    MERGE (a)-[r:IN_PORTFOLIO]->(b)\n",
    "        SET r.ann_date = (CASE WHEN ann_date <> 'NotChange' THEN toFloat(ann_date) ELSE r.ann_date END)\n",
    "        SET r.end_date = (CASE WHEN end_date <> 'NotChange' THEN toFloat(end_date) ELSE r.end_date END)\n",
    "        SET r.mkv = (CASE WHEN mkv <> 'NotChange' THEN toFloat(mkv) ELSE r.mkv END)        \n",
    "        SET r.amount = (CASE WHEN amount <> 'NotChange' THEN toFloat(amount) ELSE r.amount END)\n",
    "        SET r.stk_mkv_ratio = (CASE WHEN stk_mkv_ratio <> 'NotChange' THEN toFloat(stk_mkv_ratio) ELSE r.stk_mkv_ratio END)        \n",
    "        SET r.stk_float_ratio = (CASE WHEN stk_float_ratio <> 'NotChange' THEN toFloat(stk_float_ratio) ELSE r.stk_float_ratio END)        \n",
    "    RETURN a,b,r\n",
    "    \",\n",
    "    {batchSize:500, parallel:false})\n",
    "    // 取消并行\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = graph.run(query_rel_fund_listed_company_portfolio)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Record batches=110 total=54559 timeTaken=31 committedOperations=54559 failedOperations=0 failedBatches=0 retries=0 errorMessages={} batch={'total': 110, 'committed': 110, 'failed': 0, 'errors': {}} operations={'total': 54559, 'committed': 54559, 'failed': 0, 'errors': {}} wasTerminated=False>\n"
     ]
    }
   ],
   "source": [
    "check_result(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新结果检查"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "针对下面两条记录会在更新前后做对比\n",
    "\n",
    "|fund|fullname|ann_date|end_date|mkv|amount|stk_mkv_ratio|stk_float_ratio|type|\n",
    "|--|--|--|--|--|--|--|--|--|\n",
    "|000001|南极电商股份有限公司|20200121|20191231|149832015.87|NotChange|4.31|NotChange|IN_PORTFOLIO|\n",
    "|000001|保利联合化工控股集团股份有限公司|20130328|20121231|8927779.35|363657.0|0.15|0.21|IN_PORTFOLIO|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"\"\"\n",
    "MATCH p = (a:FUND)-[r:IN_PORTFOLIO]->(b:COMPANY) \n",
    "WHERE a.fund_code='000001'and  b.company='{}' \n",
    "RETURN a.fund_code as fund_code,a.name as name,b.company as company,r.amount,\n",
    "       r.ann_date,r.end_date,r.mkv,r.stk_float_ratio,r.stk_mkv_ratio\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 更新关系"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于000001（华夏成长基金）持仓 南极电商股份有限公司 的信息。在 20200121 有更新。分别对 持有股票市值（mkv）和 占股票市值比 （stk_mkv_ratio）发生变化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>company</th>\n",
       "      <th>fund_code</th>\n",
       "      <th>name</th>\n",
       "      <th>r.amount</th>\n",
       "      <th>r.ann_date</th>\n",
       "      <th>r.end_date</th>\n",
       "      <th>r.mkv</th>\n",
       "      <th>r.stk_float_ratio</th>\n",
       "      <th>r.stk_mkv_ratio</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>南极电商股份有限公司</td>\n",
       "      <td>000001</td>\n",
       "      <td>华夏成长</td>\n",
       "      <td>13733457.0</td>\n",
       "      <td>20200121.0</td>\n",
       "      <td>20191231.0</td>\n",
       "      <td>1.498320e+08</td>\n",
       "      <td>0.72</td>\n",
       "      <td>4.31</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      company fund_code  name    r.amount  r.ann_date  r.end_date  \\\n",
       "0  南极电商股份有限公司    000001  华夏成长  13733457.0  20200121.0  20191231.0   \n",
       "\n",
       "          r.mkv  r.stk_float_ratio  r.stk_mkv_ratio  \n",
       "0  1.498320e+08               0.72             4.31  "
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph.run(query.format('南极电商股份有限公司')).to_data_frame()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](../pictures/update_fund_combine1.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 新增关系"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>company</th>\n",
       "      <th>fund_code</th>\n",
       "      <th>name</th>\n",
       "      <th>r.amount</th>\n",
       "      <th>r.ann_date</th>\n",
       "      <th>r.end_date</th>\n",
       "      <th>r.mkv</th>\n",
       "      <th>r.stk_float_ratio</th>\n",
       "      <th>r.stk_mkv_ratio</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>保利联合化工控股集团股份有限公司</td>\n",
       "      <td>000001</td>\n",
       "      <td>华夏成长</td>\n",
       "      <td>363657.0</td>\n",
       "      <td>20130328.0</td>\n",
       "      <td>20121231.0</td>\n",
       "      <td>8927779.35</td>\n",
       "      <td>0.21</td>\n",
       "      <td>0.15</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            company fund_code  name  r.amount  r.ann_date  r.end_date  \\\n",
       "0  保利联合化工控股集团股份有限公司    000001  华夏成长  363657.0  20130328.0  20121231.0   \n",
       "\n",
       "        r.mkv  r.stk_float_ratio  r.stk_mkv_ratio  \n",
       "0  8927779.35               0.21             0.15  "
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph.run(query.format('保利联合化工控股集团股份有限公司')).to_data_frame()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于000001（华夏成长基金）持仓 保利联合化工控股集团股份有限公司 的信息。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](../pictures/update_fund_combine2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过前后对比，可以发现，成功完成了图谱数据的更新。\n",
    "\n",
    "在实际工作时，可以结合具体的业务需要调整更新频次，每天/每周/每月。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
